package com.photoeditor.demo.ui.widget.face;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatImageView;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

import com.common.base.log.DLog;
import com.common.base.utils.DeviceUtils;
import com.photoeditor.R;
import com.photoeditor.demo.model.bean.face.FaceRectBean;
import com.photoeditor.demo.util.Utils;

import java.util.ArrayList;
import java.util.List;

public class FaceAgingScannerView extends AppCompatImageView {
    private Bitmap mBitmap;
    private List<FaceRectBean> mFaceBeans;
    private Bitmap mIcMale, mIcFemale;
    private int mPaddingX, mPaddingTop, mPaddingBottom;
    private Paint mTextPaint;
    private Bitmap mResultBitmap;

    public FaceAgingScannerView(Context context) {
        this(context, null);
    }

    public FaceAgingScannerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FaceAgingScannerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mIcMale = BitmapFactory.decodeResource(getResources(), R.drawable.ic_male);
        mIcFemale = BitmapFactory.decodeResource(getResources(), R.drawable.ic_female);
        mPaddingX = DeviceUtils.dip2px(16);
        mPaddingTop = DeviceUtils.dip2px(16 + 20);
        mPaddingBottom = DeviceUtils.dip2px(16);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setTypeface(Typeface.DEFAULT_BOLD);
        mTextPaint.setTextSize(DeviceUtils.dip2px(18));
        mTextPaint.setTextAlign(Paint.Align.CENTER);
        mTextPaint.setColor(Color.parseColor("#FFFFFFFF"));
    }


    public void setBitmap(Bitmap bitmap) {
        mBitmap = fillet(bitmap, DeviceUtils.dip2px(22), 0);
    }

    public void setFaceBeans(List<FaceRectBean> list) {
        mFaceBeans = list;
    }

    private boolean mCheckOnce = true;
    private boolean mAddPaddingTop = false;
    private int mWidth, mHeight;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mBitmap != null) {
            if (mCheckOnce) {
                mCheckOnce = false;
                mAddPaddingTop = checkTop(mBitmap.getWidth(), mBitmap.getHeight(), true);
                sortData();
                checkOverlay();
                //重置高度
                if (mAddPaddingTop) {
                    RelativeLayout.LayoutParams lps = (RelativeLayout.LayoutParams) getLayoutParams();
                    lps.height = getHeight() + DeviceUtils.dip2px(20);
                    setLayoutParams(lps);
                    postInvalidate();
                    return;
                }
            }
            if (mWidth < getWidth()) {
                mWidth = getWidth();
            }
            if (mHeight < getHeight()) {
                mHeight = getHeight();
            }
            //绘制图片
            RectF dst;
            DLog.d("sLog", "height " + mHeight);
            if (mAddPaddingTop) {
                dst = new RectF(mPaddingX, mPaddingTop, mWidth - mPaddingX, mHeight - mPaddingBottom);
            } else {
                dst = new RectF(mPaddingX, mPaddingX, mWidth - mPaddingX, mHeight - mPaddingX);
            }
            canvas.drawBitmap(mBitmap, null, dst, null);

            //绘制标记
            drawFaceTag(canvas);
        }
    }

    public Bitmap getReusltBitmap() {
        if (mResultBitmap == null || mResultBitmap.isRecycled()) {
            setDrawingCacheEnabled(true);
            mResultBitmap = Bitmap.createBitmap(getDrawingCache());
            setDrawingCacheEnabled(false);
        }
        return mResultBitmap;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mBitmap != null && !mBitmap.isRecycled()) {
            mBitmap.recycle();
        }
        if (mResultBitmap != null && !mResultBitmap.isRecycled()) {
            mResultBitmap.recycle();
        }
    }

    private boolean checkTop(int bmpWidth, int bmpHeight, boolean isFirst) {
        float scaleX;
        float scaleY;
        if (isFirst) {
            scaleX = (float) (getWidth() - 2 * mPaddingX) / (float) mBitmap.getWidth();
            scaleY = (float) (getHeight() - 2 * mPaddingX) / (float) mBitmap.getHeight();
        } else {
            scaleX = (float) (getWidth() - 2 * mPaddingX) / (float) mBitmap.getWidth();
            scaleY = (float) (getHeight() - mPaddingTop - mPaddingBottom) / (float) mBitmap.getHeight();
        }
        if (mFaceBeans == null || mFaceBeans.isEmpty()) {
            return false;
        }
        boolean outOfTop = false;
        for (FaceRectBean bean : mFaceBeans) {
            String gender = TextUtils.isEmpty(bean.getGender()) ? "" : bean.getGender().toLowerCase();
            int width;
            int height;
            if (TextUtils.equals(gender, "male")) {
                width = mIcMale.getWidth();
                height = mIcMale.getHeight();
            } else {
                width = mIcFemale.getWidth();
                height = mIcFemale.getHeight();
            }

            float offsetY = bean.getHeight() * scaleY / 3;

            float centerX = (bean.getLeft() + bean.getWidth() / 2) * scaleX + mPaddingX;
            float tagLeft = centerX - width / 2;
            float tagRight = centerX + width / 2;
            if (tagLeft < 0) {
                //图标左边超出了边界
                tagLeft = 0;
                tagRight = width;
            }
            if (tagRight > DeviceUtils.getScreenWidthPx()) {
                //图标右边超出了边界
                tagRight = DeviceUtils.getScreenWidthPx();
                tagLeft = tagRight - width;
            }
            float tagBottom = bean.getTop() - offsetY + (isFirst ? mPaddingBottom : mPaddingTop);
            float tagTop = tagBottom - height;
            if (tagTop < 0) {
                //图标上面超出了边界
                //不要着急重置tagTop为0,先尝试在上面增加20dp的padding
                if (isFirst) {
                    DLog.d("FaceAgingScannerViewLog", "out of top " + tagTop);
                    outOfTop = true;
                    checkTop(bmpWidth, bmpHeight, false);
                    return outOfTop;
                }
                tagTop = 0;
                tagBottom = height;
            }
            bean.setEffectLeft(tagLeft);
            bean.setEffectTop(tagTop);
            bean.setEffectRight(tagRight);
            bean.setEffectBottom(tagBottom);
        }
        return outOfTop;
    }

    /**
     * 按照Rect从右向左排序
     */
    private void sortData() {
        quickSort();
    }

    private void checkOverlay() {
        //mFaceBeans已经排好序,0是最先绘制的
        //倒序遍历
        int size = mFaceBeans.size();
        for (int i = size - 1; i > 0; i--) {
            FaceRectBean bean1 = mFaceBeans.get(i);
            if (bean1.isOmitted()) {
                continue;
            }
            for (int j = i - 1; j > 0; j--) {
                FaceRectBean bean2 = mFaceBeans.get(j);
                Rect rect1 = new Rect((int) bean1.getEffectLeft(), (int) bean1.getEffectTop(), (int) bean1.getEffectRight(), (int) bean1.getEffectBottom());
                Rect rect2 = new Rect((int) bean2.getEffectLeft(), (int) bean2.getEffectTop(), (int) bean2.getEffectRight(), (int) bean2.getEffectBottom());
                boolean covered = Utils.oneRectOverlayAnotherInLimit(rect2, rect1, 0.5f);
                if (covered) {
                    bean2.setOmitted(true);
                }
            }
        }

        List<FaceRectBean> list = new ArrayList<>();
        for (FaceRectBean data : mFaceBeans) {
            if (!data.isOmitted()) {
                list.add(data);
            } else {
                DLog.d("sLog", "omit one");
            }
        }
        mFaceBeans = list;
    }

    private void quickSort() {
        int size = mFaceBeans.size();
        quickSort(mFaceBeans, 0, size - 1);
    }

    private void quickSort(List<FaceRectBean> list, int start, int end) {
        int i = start, j = end;
        float target = list.get(start).getEffectRight();
        while (i < j) {
            while (i < j && target >= list.get(j).getEffectRight())
                j--;
            if (i < j) {
                exchangeValue(list.get(j), list.get(i));
            }
            while (i < j && list.get(i).getEffectRight() >= target)
                i++;
            if (i < j) {
                exchangeValue(list.get(j), list.get(i));
            }
        }
        if (i - 1 > start) {
            quickSort(list, start, i - 1);
        }

        if (j + 1 < end) {
            quickSort(list, j + 1, end);
        }
    }

    private void exchangeValue(FaceRectBean bean1, FaceRectBean bean2) {
        int age1 = bean1.getAge();
        String gender1 = bean1.getGender();
        int left1 = bean1.getLeft();
        int top1 = bean1.getTop();
        int width1 = bean1.getWidth();
        int height1 = bean1.getHeight();
        float effectLeft1 = bean1.getEffectLeft();
        float effectTop1 = bean1.getEffectTop();
        float effectRight1 = bean1.getEffectRight();
        float effectBottom1 = bean1.getEffectBottom();

        bean1.setAge(bean2.getAge());
        bean1.setGender(bean2.getGender());
        bean1.setLeft(bean2.getLeft());
        bean1.setTop(bean2.getTop());
        bean1.setWidth(bean2.getWidth());
        bean1.setHeight(bean2.getHeight());
        bean1.setEffectLeft(bean2.getEffectLeft());
        bean1.setEffectTop(bean2.getEffectTop());
        bean1.setEffectRight(bean2.getEffectRight());
        bean1.setEffectBottom(bean2.getEffectBottom());

        bean2.setAge(age1);
        bean2.setGender(gender1);
        bean2.setLeft(left1);
        bean2.setTop(top1);
        bean2.setWidth(width1);
        bean2.setHeight(height1);
        bean2.setEffectLeft(effectLeft1);
        bean2.setEffectTop(effectTop1);
        bean2.setEffectRight(effectRight1);
        bean2.setEffectBottom(effectBottom1);
    }

    private void drawFaceTag(Canvas canvas) {
        if (mFaceBeans == null || mFaceBeans.isEmpty()) {
            return;
        }
        for (FaceRectBean bean : mFaceBeans) {
            String gender = TextUtils.isEmpty(bean.getGender()) ? "" : bean.getGender().toLowerCase();

            float textOffset;
            //绘制男女图片
            if (TextUtils.equals(gender, "male")) {
                canvas.drawBitmap(mIcMale, null, new RectF(bean.getEffectLeft(), bean.getEffectTop(), bean.getEffectRight(), bean.getEffectBottom()), null);
                textOffset = (float) mIcMale.getWidth() / 4;
            } else {
                canvas.drawBitmap(mIcFemale, null, new RectF(bean.getEffectLeft(), bean.getEffectTop(), bean.getEffectRight(), bean.getEffectBottom()), null);
                textOffset = (float) mIcMale.getWidth() / 4;
            }
            //绘制年龄文字
            Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
            float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
            float baseline = (bean.getEffectTop() + bean.getEffectBottom()) / 2 + distance;
            float x = (bean.getEffectLeft() + bean.getEffectRight()) / 2 + textOffset;
//            if (bean.isOmitted()) {
//                mTextPaint.setColor(Color.RED);
//            } else {
//                mTextPaint.setColor(Color.WHITE);
//            }
            canvas.drawText(String.valueOf(bean.getAge()), x, baseline, mTextPaint);
        }
    }

    private Bitmap fillet(Bitmap bitmap, int roundPx, int corners) {
        try {
            // 其原理就是：先建立一个与图片大小相同的透明的Bitmap画板
            // 然后在画板上画出一个想要的形状的区域。
            // 最后把源图片帖上。
            final int width = bitmap.getWidth();
            final int height = bitmap.getHeight();

            Bitmap paintingBoard = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(paintingBoard);
            canvas.drawARGB(Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT);

            final Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.BLACK);

            //画出4个圆角
            final RectF rectF = new RectF(0, 0, width, height);
            canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

            //帖子图
            final Rect src = new Rect(0, 0, width, height);
            final Rect dst = src;
            canvas.drawBitmap(bitmap, src, dst, paint);
            return paintingBoard;
        } catch (Exception exp) {
            return bitmap;
        }
    }
}
